﻿#light
open System.Collections.Generic

// "Implementor"
type DataObject =
    abstract NextRecord : unit -> unit
    abstract PriorRecord : unit -> unit
    abstract NewRecord : string -> unit
    abstract DeleteRecord : string -> unit
    abstract ShowRecord : unit -> unit
    abstract ShowAllRecords : unit -> unit

// "ConcreteImplementor"
type CustomersData() =
    let customers = new List<string>()
    let mutable current = 0
    do customers.Add("Jim Jones")
    do customers.Add("Samual Jackson")
    do customers.Add("Allen Good")
    do customers.Add("Ann Stills")
    do customers.Add("Lisa Giolani")
                
    interface DataObject with
        member this.NextRecord() =
            if (current <= customers.Count - 1)
                then current <- current + 1

        member this.PriorRecord() =
            if (current > 0)
                then current <- current - 1

        member this.NewRecord(name) =
            customers.Add(name)

        member this.DeleteRecord(name) =
            customers.Remove(name) |> ignore

        member this.ShowRecord() =
            printfn "%s" customers.[current]

        member this.ShowAllRecords() =
            customers
            |> Seq.iter (fun c -> printfn " %s" c)

// "Abstraction"
type CustomersBase(group: string, dataObj: DataObject) =
    let mutable data = dataObj
    
    member this.Data with get() = data
                     and set v = data <- v

    member this.Next() =
        this.Data.NextRecord()

    member this.Prior() =
        this.Data.PriorRecord()

    member this.New(name) =
        this.Data.NewRecord(name)

    member this.Delete(name) =
        this.Data.DeleteRecord(name)

    member this.Show() =
        this.Data.ShowRecord()

    abstract ShowAll : unit -> unit
    default this.ShowAll() =
        printfn "Customer Group: %s" group
        this.Data.ShowAllRecords()

// "RefinedAbstraction"
type Customers(group, data: DataObject) =
    inherit CustomersBase(group, data)

    override this.ShowAll() =
        // Add separator lines
        printfn ""
        printfn "------------------------"
        base.ShowAll()
        printfn "------------------------"

